/*
 * Fichier: Education.java
 * Crée le: 03 décembre 2006.
 * Modifié: 7 juillet 2007.
 * Auteurs: Sébastien ESTIENNE.
 * SiteWeb: http://www.prog-info.org/
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

package chapitre5;



import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;



/**
 * <p>Programme qui aide les étudiants de niveau élémentaire à apprendre l'addition, la
 * soustraction, la multiplication et la division.</p>
 * @author Sébastien ESTIENNE.
 */
public class Education extends JFrame implements ActionListener
{
   /**
    * <p>Serial version UID.</p>
    */
   private static final long serialVersionUID = 1L;

   /** Solution de l'opération. */
   private int solution = 0;

   /** Nombre de réponses correctes. */
   private int nbRepCorrectes = 0;

   /** Nombre de réponses fausses. */
   private int nbRepFausses = 0;

   /** Niveau de difficulté. */
   private int niveau = 0;

   /** Type d'exercice (+, -, *, /, tous). */
   private int typeExo = 0;

   /** L'opération entre les deux nomrbes. */
   private char cOperateur = '+';

   /** Etiquette pour la question. */
   private JLabel etiquetteQuestion;

   /** Etiquette pour la réponse. */
   private JLabel etiquetteReponse;

   /** Champ texte pour la réponse. */
   private JTextField champReponse;

   /** Etiquette pour un commentaire. */
   private JLabel etiquetteCommentaire;


   /**
    * <p>Construit l'application.</p>
    */
   public Education()
   {
      // Appel du constructeur de la classe JFrame.
      super("Education");

      // Obtenir le panneau de contenu et changer son layout en un FlowLayout.
      Container conteneur = getContentPane();
      conteneur.setLayout(new FlowLayout());

      // Créer l'étiquette et le champ texte du nombre à deviner.
      this.etiquetteQuestion = new JLabel("");
      conteneur.add(this.etiquetteQuestion);

      this.etiquetteReponse = new JLabel("Votre réponse : ");
      conteneur.add(this.etiquetteReponse);

      this.champReponse = new JTextField(5);
      this.champReponse.setEditable(true);
      conteneur.add(this.champReponse);
      this.champReponse.addActionListener(this);

      this.etiquetteCommentaire = new JLabel("");
      conteneur.add(this.etiquetteCommentaire);

      // Initialiser le niveau de difficulté.
      iniNiveau();

      // Initialiser le type d'exercice.
      iniExercice();

      // Initialiser la question.
      nouvelleQuestion();

      // Modifie les propriétés de la fenêtre.
      setSize(210, 110);
      setLocation(100, 100);
      setVisible(true);
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   }


   /**
    * <p>Traiter une réponse.</p>
    * @param actionEvent Un événement sémantique qui indique qu'une action s'est produite dans le
    *        composant concerné.
    */
   public void actionPerformed(ActionEvent actionEvent)
   {
      // Reponse de l'utilisateur.
      int reponse = 0;
      // Indique si la réponse est valide ou non.
      boolean valide = true;

      // Convertir le nombre entré par l'utilisateur.
      try
      {
         reponse = Integer.parseInt(this.champReponse.getText());
      }
      // Traite le cas lorsque la valeur rentrée par l'utilisateur n'est pas un nombre entier.
      catch(NumberFormatException e)
      {
         valide = false;
      }

      // Vider les champs.
      this.champReponse.setText("");
      this.etiquetteCommentaire.setText("");

      // Vérifier la validité de la réponse.
      String commentaire = "";
      if(valide && reponse == this.solution)
      {
         commentaire = reponseCorrecte();
         this.nbRepCorrectes++;
         nouvelleQuestion();
      }
      else
      {
         commentaire = reponseFausse();
         this.nbRepFausses++;
      }

      // Modifie les commentaires suite à la réponse de l'utilisateur.
      this.etiquetteCommentaire.setText(commentaire);

      // Cas de fin de l'exercice.
      if(this.nbRepCorrectes + this.nbRepFausses == 10)
      {
         // Message de taux de réussite.
         String message;

         // Taux de réussite.
         int taux;

         taux = this.nbRepCorrectes * 100 / (this.nbRepCorrectes + this.nbRepFausses);
         message = "Taux de réussite : " + taux + "%.";

         if(taux < 75)
         {
            message += "\n\nDemande à ton professeur de t'aider.";
         }

         // Affiche le résultat.
         JOptionPane.showMessageDialog(null, message, "Taux de réussite",
               JOptionPane.INFORMATION_MESSAGE);

         // Initialisation pour l'exercice suivant.
         iniNiveau();
         iniExercice();
         nouvelleQuestion();
         this.nbRepCorrectes = 0;
         this.nbRepFausses = 0;
      }

   }


   /**
    * <p>Génère un nombre aléatoire.</p>
    * @return Le nombre généré aléatoirement.
    */
   public int genereNombre()
   {
      return (1 + (int) (Math.random() * Math.pow(10.0, this.niveau)));
   }


   /**
    * <p>Afficher une nouvelle question dans la barre d'état.</p>
    */
   public void nouvelleQuestion()
   {
      // Initialiser les nombres.
      int nombre1 = genereNombre();
      int nombre2 = genereNombre();

      // Génère un opérateur.
      if(this.typeExo == 5)
      {
         // Nombre aléatoire entre 0 et 3.
         int i = (int) (Math.random() * 4);

         // Sélectionne un type d'opération au hasard.
         switch(i)
         {
         case 1:
            this.cOperateur = '+';
            break;
         case 2:
            this.cOperateur = '-';
            break;
         case 3:
            this.cOperateur = '*';
            break;
         default:
            this.cOperateur = '/';
            break;
         }
      }

      // Calculer la solution.
      switch(this.typeExo)
      {
      case 1:
         this.solution = nombre1 + nombre2;
         break;
      case 2:
         this.solution = nombre1 - nombre2;
         break;
      case 3:
         this.solution = nombre1 * nombre2;
         break;
      case 4:
         this.solution = nombre1 / nombre2;
         break;
      default:
         break;
      }

      // Met à jour la question.
      this.etiquetteQuestion.setText("Combien font " + nombre1 + " " + this.cOperateur + " "
            + nombre2 + ".");
   }


   /**
    * <p>Sélectionne au hasard une phrase de réponse correcte.</p>
    * @return La réponse correcte au hasard.
    */
   public String reponseCorrecte()
   {
      // Nombre aléatoire entre 0 et 3.
      int i = (int) (Math.random() * 4);

      // Initialisation de la phrase en fonction du nombre aléatoire.
      switch(i)
      {
      case 0:
         return "C'est très bien!";
      case 1:
         return "Excellent!";
      case 2:
         return "Tu fais du beau travail!";
      default:
         return "Bonne réponse, continue!";
      }
   }


   /**
    * <p>Sélectionne au hasard une phrase de réponse fausse.</p>
    * @return La réponse fausse au hasard.
    */
   public String reponseFausse()
   {
      // Nombre aléatoire entre 0 et 3.
      int i = (int) (Math.random() * 4);

      // Initialisation de la phrase en fonction du nombre aléatoire.
      switch(i)
      {
      case 0:
         return "Désolé, essai encore.";
      case 1:
         return "Mauvaise réponse. Essaie encore.";
      case 2:
         return "Ne lâche pas, tu y es presque!";
      default:
         return "Non, essaie à nouveau.";
      }
   }


   /**
    * <p>Initialisation du niveau de difficulté.</p>
    */
   public void iniNiveau()
   {
      String sNiveau = "";

      this.niveau = 0;

      // Demander à l'utilisateur le niveau de difficulté tant que le niveau saisi est incorrect.
      while(this.niveau < 1 || this.niveau > 3)
      {
         sNiveau = JOptionPane.showInputDialog("Entrez le niveau de difficulté : \n"
               + " 1 - Facile\n" + " 2 - Moyen\n" + " 3 - Difficile\n\n");

         try
         {
            this.niveau = Integer.parseInt(sNiveau);
         }
         catch(NumberFormatException e)
         {
            this.niveau = -1;
         }
      }
   }


   /**
    * <p>Initialisation du type d'exercice.</p>
    */
   public void iniExercice()
   {
      String sTypeExo;

      this.typeExo = 0;

      // Demander à l'utilisateur le type d'exercice tant que le niveau saisi est incorrect.
      while(this.typeExo < 1 || this.typeExo > 5)
      {
         sTypeExo = JOptionPane.showInputDialog("Entrez le niveau de difficulté : \n"
               + " 1 - Addition\n" + " 2 - Soustraction\n" + " 3 - Multiplication\n"
               + " 4 - Division\n" + " 5 - Tous types\n\n");

         try
         {
            this.typeExo = Integer.parseInt(sTypeExo);
         }
         catch(NumberFormatException e)
         {
            this.typeExo = -1;
         }
      }

      // Sélectionne un type d'opération.
      switch(this.typeExo)
      {
      case 1:
         this.cOperateur = '+';
         break;
      case 2:
         this.cOperateur = '-';
         break;
      case 3:
         this.cOperateur = '*';
         break;
      case 4:
         this.cOperateur = '/';
         break;
      default:
         break;
      }
   }


   /**
    * <p>Lance l'application.</p>
    * @param args Les paramètres de la ligne de commande.
    */
   public static void main(String[] args)
   {
      new Education();
   }
}
